package cc.liyinghao.service.impl;

import cc.liyinghao.common.dto.IdUsernameDTO;
import cc.liyinghao.common.en.MessageType;
import cc.liyinghao.common.pojo.ChatList;
import cc.liyinghao.common.pojo.Message;
import cc.liyinghao.common.pojo.ViewUserMessages;
import cc.liyinghao.config.DefaultIpPrefixConfig;
import cc.liyinghao.mapper.*;
import cc.liyinghao.param.RecordParam;
import cc.liyinghao.param.SendMessageParam;
import cc.liyinghao.response.MessageVo;
import cc.liyinghao.response.RecallVo;
import cc.liyinghao.service.ContactsService;
import cc.liyinghao.service.MessageService;
import cc.liyinghao.service.WebSocketService;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@Slf4j
@RequiredArgsConstructor
public class MessageServiceImpl implements MessageService {

    private final DefaultIpPrefixConfig defaultIpPrefixConfig;
    private final ViewUserMessagesMapper viewUserMessagesMapper;
    private final UserMessagesMapper userMessagesMapper;
    private final ChatListMapper chatListMapper;
    private final SysContactsMapper sysContactsMapper;
    private final SysUserMapper sysUserMapper;
    private final WebSocketService webSocketService;
    private final ContactsService contactsService;

    @Override
    public void send(Integer userId, SendMessageParam sendMessageParam) {
        // 判断是向群组发送还是向用户发送
        if (sendMessageParam.getTargetId() >= 10000000) {
            // 群组
            sendMessageToGroup(userId, sendMessageParam);
        } else {
            // 个人
            sendMessageToUser(userId, sendMessageParam);
        }
    }

    @Override // 聊天记录
    public List<MessageVo> record(int userId, RecordParam recordParam) {
        Page<ViewUserMessages> page = new Page<>(recordParam.getIndex(), recordParam.getNum());
        LambdaQueryWrapper<ViewUserMessages> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .select(ViewUserMessages::getId,
                        ViewUserMessages::getFromUsername,
                        ViewUserMessages::getToUsername,
                        ViewUserMessages::getContent,
                        ViewUserMessages::getCreateTime,
                        ViewUserMessages::getType)
                .eq(ViewUserMessages::getFromId, userId)
                .or()
                .eq(ViewUserMessages::getToId, userId)
                .or()
                .eq(ViewUserMessages::getFromId, recordParam.getTargetId())
                .or()
                .eq(ViewUserMessages::getToId, recordParam.getTargetId())
                .orderByDesc(ViewUserMessages::getCreateTime);
        // List<ViewUserMessages> viewUserMessages = viewUserMessagesMapper.selectPage(page, queryWrapper).getRecords();
        // System.out.println(viewUserMessages);
        return userMessagesMapper.getRecord(userId, recordParam.getTargetId(),
                recordParam.getIndex(), recordParam.getNum());
    }

    @Override
    public void sendMessageToGroup(Integer userId, SendMessageParam sendMessageParam) {
        Message message = makeMessage(userId, sendMessageParam);
        webSocketService.sendMsgToGroup(message);
    }

    @Override
    public Message recall(String userId, RecallVo recallVo) {
        Message message = userMessagesMapper.selectById(recallVo.getMsgId());
        if (null == message) {
            throw new RuntimeException("消息不存在~");
        }
        if (DateUtil.between(message.getCreateTime(), new Date(), DateUnit.MINUTE) > 2) {
            throw new RuntimeException("消息已超过2分钟，无法撤回~");
        }
        //撤回自己的消息
        message.setType(MessageType.Recall);
        return message;
    }

    public void sendMessageToUser(Integer userId, SendMessageParam sendMessageParam) {
        //1.判断目标用户是不是联系人
        if (!contactsService.isContact(userId, sendMessageParam.getTargetId())) {
            throw new RuntimeException("非联系人");
        }
        //2.构建消息
        Message message = makeMessage(userId, sendMessageParam);
        List<Integer> ids = Arrays.asList(message.getFromId(), message.getToId());
        //3.根据id查询用户名
        Map<Integer, String> userName = sysUserMapper.selectIdUsernameListByIds(ids).stream()
                .collect(Collectors.toMap(IdUsernameDTO::getId, IdUsernameDTO::getUsername));
        //4.构建返回前端VO对象                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    象
        MessageVo messageVo = new MessageVo();
        messageVo.setId(message.getId());
        messageVo.setFromUsername(userName.get(message.getFromId()));
        messageVo.setToUsername(userName.get(message.getToId()));
        messageVo.setCreateTime(String.valueOf(message.getCreateTime()));
        messageVo.setType(message.getType());
        messageVo.setContent(message.getContent());
        webSocketService.sendMsgToUser(messageVo, userId.toString(), String.valueOf(sendMessageParam.getTargetId()));
    }

    /**
     * 发送消息，目的是保存消息到数据库 和更新消息列表
     */
    public Message makeMessage(int userId, SendMessageParam sendMessageParam) {
        Message message = new Message();
        message.setFromId(userId);
        message.setIsDel(0);
        message.setToId(sendMessageParam.getTargetId());
        message.setContent((String) sendMessageParam.getMsgContent());
        message.setReferenceMsg(StrUtil.isEmpty(sendMessageParam.getReferenceMsgId()) ? null : Integer.valueOf(sendMessageParam.getReferenceMsgId()));
        message.setType(sendMessageParam.getType());
        // 查找消息列表(chatList)中是否存在
        LambdaQueryWrapper<ChatList> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .select(ChatList::getId)
                .eq(ChatList::getTargetId, message.getToId());
        ChatList chatList = new ChatList();
        ChatList id = chatListMapper.selectOne(queryWrapper);
        // 更新chatList
        // TODO 以后可以优化 单独有一个新建聊天列表的接口
        if (id != null) {  //存在
            chatList.setId(id.getId());
            chatList.setLastMessage(message.getContent());
            chatList.setType(message.getType());
            chatListMapper.updateById(chatList);
        } else { //不存在
            chatList.setUserId(userId);
            chatList.setTargetId(message.getToId());
            chatList.setLastMessage(message.getContent());
            chatList.setType(message.getType());
            chatListMapper.insert(chatList);
        }
        // 保存消息到数据库
        userMessagesMapper.insert(message);
        return message;
    }

}
